using System;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security;
#if !PocketPC && Framework20
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
#endif

namespace GeoFramework.IO
{

	/// <summary>
	/// Summary description for NativeMethods.
	/// </summary>
#if !PocketPC && Framework20
    [SuppressUnmanagedCodeSecurity]
#endif
    internal 
#if Framework20
		static 
#else
		sealed
#endif	
		class NativeMethods
	{
#if !Framework20
        private NativeMethods()
        {
        }
#endif



        #region API's for Setting the System Clock

        public static int SetLocalTime(ref SYSTEMTIME lpSystemTime)
		{
#if PocketPC
			if(Environment.OSVersion.Platform == System.PlatformID.WinCE)
			{
					return SetLocalTimeCompact(ref lpSystemTime);
			}
			else
#endif
			return SetLocalTimeDesktop(ref lpSystemTime);
		}

		[DllImport("kernel32.dll", EntryPoint="SetLocalTime", SetLastError=true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        private static extern int SetLocalTimeDesktop(ref SYSTEMTIME lpSystemTime);

#if PocketPC
		[DllImport("coredll.dll", EntryPoint="SetLocalTime", SetLastError=true)] 
		private static extern int SetLocalTimeCompact(ref SYSTEMTIME lpSystemTime);
#endif

        #endregion

        #region API's for Controlling the GPS Intermediate Driver
#if PocketPC
        internal enum DeviceIoDeviceType : int
        {
            FileDeviceService = 0x00000104
        }

        /// <summary>
        /// Controls the method of channeling data to the device during DeviceIoControl calls
        /// </summary>
        internal enum DeviceIoMethod : int
        {
            Buffered = 0,
            In = 1,
            Out = 2,
            Neither = 3
        }

        /// <summary>
        /// Controls the access type used during DeviceIoControl calls
        /// </summary>
        internal enum DeviceIoAccess : int
        {
            AnyAccess = 0,
            Read = 1,
            Write = 2
        }

        private static int ControlCode(DeviceIoDeviceType deviceType,
            int function, DeviceIoMethod method, DeviceIoAccess access)
        {
            return (int)deviceType << 16
                    | (int)access << 14
                    | function << 2
                    | (int)method;
        }

        public static uint IOCTL_SERVICE_REFRESH
        {
            get
            {
                return (uint)ControlCode(DeviceIoDeviceType.FileDeviceService, 3, DeviceIoMethod.Buffered, DeviceIoAccess.AnyAccess);
            }
        }

        public static int DeviceIoControl(SafeFileHandle hDevice, uint dwIoControlCode)
        {
            return DeviceIoControl(hDevice, dwIoControlCode, new byte[] { }, new byte[] { });
        }

        public static int DeviceIoControl(
                    SafeFileHandle hDevice, uint dwIoControlCode,
                    byte[] input, byte[] output)
        {
            int BytesReturned = 0;
#if PocketPC
            if (Environment.OSVersion.Platform == System.PlatformID.WinCE)
            {
                return DeviceIoControlCompact(hDevice.DangerousGetHandle(),
                    dwIoControlCode, input, input.Length, output, output.Length,
                    ref BytesReturned, IntPtr.Zero);
            }
            else
#endif
                return DeviceIoControlDesktop(hDevice.DangerousGetHandle(),
                    dwIoControlCode, input, input.Length, output, output.Length,
                    ref BytesReturned, IntPtr.Zero);
        }

        [DllImport("coredll.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
        internal static extern int DeviceIoControlCompact(
            IntPtr hDevice, uint dwIoControlCode, byte[] lpInBuffer,
            int nInBufferSize, byte[] lpOutBuffer, int nOutBufferSize,
            ref int lpBytesReturned, IntPtr lpOverlapped);

        [DllImport("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern int DeviceIoControlDesktop(
            IntPtr hDevice, uint dwIoControlCode, byte[] lpInBuffer,
            int nInBufferSize, byte[] lpOutBuffer, int nOutBufferSize,
            ref int lpBytesReturned, IntPtr lpOverlapped);
#endif
        #endregion
    }

	// Structure used for date/time API's
	internal struct SYSTEMTIME
	{
		public short Year;
		public short Month;
		public short DayOfWeek;
		public short Day;
		public short Hour;
		public short Minute;
		public short Second;
		public short Milliseconds;
	}
}
